﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using XNA_Game_Engine.Characters;
using XNA_Game_Engine.Sounds;

namespace XNA_Game_Engine.GUI
{
    public static class StaticGui
    {
        public static int slotsSize = 55;

        public static List<Texture2D> Image { set; get; }
        public static GuiSlot DraggedSlot { set; get; }
        //public static GuiSlotList DraggedPanel { set; get; }
        public static GuiSlotList PanelForCommands { set; get; }
        public static GuiSlotList AvailableCommands { set; get; }
        public static GuiSlotList FunctionCommands { set; get; }
        public static GuiSlotList SelectedPanel { set; get; }
        public static MouseState MouseState { set; get; }
        public static GuiSlot SelectedSlot { set; get; }
        public static GuiSlot FunctionSelectedSlot { set; get; }
        //public static AppMouseStates AppMouseState { set; get; }
        //public static Vector2 KeepMouseStateForDragPanel { set; get; }
        //public static Vector2 DxDyForDragPanel { set; get; }
        public static SpriteFont Font { set; get; }

        public static TimeAndStart TimeStart { set; get; }
        public static OptionsMenu OptionMenu { set; get; }

        public static Buttons PlayButton { set; get; }
        public static Buttons StopButton { set; get; }

        public static Character PlayerReference;

        private static bool _mouseIsBeingUsed;

        public static void StaticGuiInit()
        {
            TimeStart = new TimeAndStart();
            OptionMenu = new OptionsMenu();
            Image = new List<Texture2D>();
            _mouseIsBeingUsed = false;
            //AppMouseState = AppMouseStates.None;
        }

        public static void Update(GameTime gameTime)
        {
            MouseState = Mouse.GetState();

            //if (DraggedPanel != null)
            //{
            //    DxDyForDragPanel = new Vector2(MouseState.X - KeepMouseStateForDragPanel.X, MouseState.Y - KeepMouseStateForDragPanel.Y);
            //    KeepMouseStateForDragPanel = new Vector2(MouseState.X, MouseState.Y);
            //    DraggedPanel.DragNow(DxDyForDragPanel);
            //}

            PanelForCommands.Update(gameTime);
            AvailableCommands.Update(gameTime);
            FunctionCommands.Update(gameTime);
            TimeStart.Update(gameTime);

            PlayButton.Update(gameTime);
            StopButton.Update(gameTime);

            OptionMenu.Update(gameTime);
        }

        public static void Draw(SpriteBatch render)
        {
            PlayButton.Draw(render);
            StopButton.Draw(render);

            PanelForCommands.Draw(render);
            AvailableCommands.Draw(render);
            FunctionCommands.Draw(render);
            TimeStart.Draw(render);

            OptionMenu.Draw(render);

            if (DraggedSlot != null)
            {
                // render.Draw(DraggedSlot.Sprite, new Vector2(MouseState.X - (DraggedSlot.ThisObject.Width / 2), MouseState.Y - (DraggedSlot.ThisObject.Height / 2)), Color.White);

                Rectangle drawRect = new Rectangle(MouseState.X - (DraggedSlot.ThisObject.Width/2),
                                                   MouseState.Y - (DraggedSlot.ThisObject.Height/2),
                                                   DraggedSlot.ThisObject.Width, DraggedSlot.ThisObject.Height);

                Rectangle targetRect = new Rectangle(0, 0, DraggedSlot.Sprite.Width, DraggedSlot.Sprite.Height);

                render.Draw(DraggedSlot.Sprite, drawRect, targetRect, Color.White);
            }

        }

        #region aplicationMouseState
        public enum AppMouseStates
        {
            Click,
            DoubleClick,
            None
        }
        #endregion
        #region GameHandling
        public static bool gameStarted //Retornando se jogo começou ou stopou.
        {
            get { return TimeStart.gameStarted; }
        }

        public static double runningTime //Retonando o tempo decorrido do jogo.
        {
            get { return TimeStart.runningTime; }
        }

        public static bool CheckTime(GameTime gameTime, double time)
        {
            return time + 200 < gameTime.TotalGameTime.TotalMilliseconds;
        }
        #endregion
        #region Drag
        public static void StartDrag(GuiSlot draggedSlot)
        {
            DraggedSlot = draggedSlot;
        }

        //public static void StartDrag(GuiSlotList draggedPanel)
        //{
        //    DraggedPanel = draggedPanel;
        //    KeepMouseStateForDragPanel = new Vector2(MouseState.X, MouseState.Y);
        //}

        public static void StopDrag()
        {
            DraggedSlot = null;
            //DraggedPanel = null;
        }
        #endregion
        #region Drag and Mouse Handling
        public static void SelectThisPanel(GuiSlotList selectedPanel)
        {
            SelectedPanel.IsSelected = false;
            SelectedPanel = selectedPanel;
            SelectedPanel.IsSelected = true;
        }

        public static bool IsMouseBeingUsed()
        {
            return DraggedSlot != null || _mouseIsBeingUsed;
        }

        public static bool IsDragging()
        {
            return DraggedSlot != null;
        }

        public static void UsingMouse(bool usingMouse)
        {
            _mouseIsBeingUsed = usingMouse;
        }

        public static Rectangle MouseAsRectangle()
        {
            return new Rectangle(MouseState.X, MouseState.Y, 1, 1);
        }

        public static bool MouseColision(Rectangle obj)
        {
            return obj.Intersects(MouseAsRectangle());
        }
        #endregion
        #region DragAction
        public static GuiSlot NewSlot(GuiSlot slot1, GuiSlot slot2)
        {
            var slot = new GuiSlot(slot1.ThisObject, slot1.ColumnPosition,
                               slot1.LinePosition, (slot2 == null ? Image[6] : slot2.Sprite),
                               true, slot1.Father, slot2 == null ? null : slot2.Tooltip)
            {
                MouseClick = slot2 == null ? null : slot2.MouseClick,
                MouseRightClick = slot2 == null ? null : slot2.MouseRightClick,
                Actions = slot2 == null ? null : slot2.Actions,
                //MouseDoubleClick = null,
                DoDragAction = slot2 == null ? null : slot2.DoDragAction
            };

            slot.GetTooltipPosision();

            return slot;
        }

        public static Action<GuiSlot> DragAction = g =>
        {
            GuiSlotList chosenPanel = null;

            // Console.WriteLine("joined DragAction");

            if (PanelForCommands.Colision(MouseAsRectangle()))
            {
                SoundController.playClip("slot");
                chosenPanel = PanelForCommands;
            }
            else if (FunctionCommands.Colision(MouseAsRectangle()))
            {
                SoundController.playClip("slot");
                chosenPanel = FunctionCommands;
            }
            else if (AvailableCommands.Colision(MouseAsRectangle()))
            {
                SoundController.playClip("slotMiss");

                //we must return a feedback
                //when player drag a Command into AvailableCommandPanel
                //he must know why he cant do this...
                // Console.WriteLine("returned because the panel cannot be modified");
                return;
            }

            //Console.WriteLine("Panel Chosen");

            if (chosenPanel == null)
            {
                SoundController.playClip("slotMiss");
                // Console.WriteLine("Dropped in any place and CanBeModified? " + g.CanBeModified);

                if (g.CanBeModified)
                {
                    int position = g.LinePosition * g.Father.Columns + g.ColumnPosition;
                    position += g.Father.IsFunction ? -2 : 0;
                    g.Father.Slots[position] = NewSlot(g, null);
                }
                return;
            }

            int n = 0;

            foreach (GuiSlot slot in chosenPanel.Slots)
            {
                n++;
                if (!slot.Colision(MouseAsRectangle()))
                    continue;

                // Console.WriteLine("Slot: " + n);
                if (chosenPanel.Slots[n - 1].CanBeModified)
                {
                    GuiSlot swap = NewSlot(g, chosenPanel.Slots[n - 1]);
                    chosenPanel.Slots[n - 1] = NewSlot(slot, g);

                    //if (g.CanBeModified)
                        //g.ChangeToThis(swap);
                }
                else
                {
                    // Console.WriteLine("This slot cannot be modified");
                    if (g.CanBeModified)
                        g.Clear();
                }

                break;
            }
        };

        #endregion
        #region ClickFunctions
        public static Action<GuiSlot> ClickFunction = g =>
        {
            int n = 0;
            foreach (GuiSlot slot in SelectedPanel.Slots)
            {
                n++;
                if (slot.Actions != null)
                    continue;

                if (SelectedPanel.Slots[n - 1].CanBeModified)
                {
                    SelectedPanel.Slots[n - 1] = NewSlot(slot, g);
                    SelectedPanel.Slots[n - 1].MouseClick = delegate { };
                }
                return;
            }

            Console.WriteLine("Panel Full");
        };

        public static Action<GuiSlot> RightClickFunction = g =>
        {
            if (!g.CanBeModified)
                return;

            var position = g.LinePosition * g.Father.Columns + g.ColumnPosition;
            position += g.Father.IsFunction ? -2 : 0;

            g.Father.Slots[position] = NewSlot(g, null);
        };
        #endregion
        #region Buttons Functions
        public static void ClearButtons()
        {
            PanelForCommands.ClearSlotList();
        }
        #endregion
    }
}
